<?php

namespace common\service;

use common\exception\LogicException;
use common\model\ProjectModel;
use common\model\ProjectStepCategoryConfirmConfigModel;
use common\model\TaskWorkOrderModel;
use common\model\TaskWorkOrderProblemStepCategoryModel;
use support\ErrorCode;
use support\SingletonTrait;
use Webman\Stomp\Client;

class TaskWorkOrderProblemStepCategoryService
{
    use SingletonTrait;

    public $projectModel;
    public function __construct(){
        $this->projectModel = model(ProjectModel::class);
    }

    const PROJECT_STATUS_START = 1; // 未开始
    const PROJECT_STATUS_COMPLETED = 4; //进行中
    const PROJECT_STATUS_CANCEL = 3; // 取消
    const PROJECT_STATUS_IN_PROGRESS = 7;     // 已完成

    const TASK_WORK_ORDER_STATUS_NOT_PROCESSED = 0; // 未处理
    const TASK_WORK_ORDER_STATUS_PROCESSED = 1; // 已处理
    const TASK_WORK_ORDER_STATUS_REVOKED = 2;   // 已撤销的工单
    const TASK_WORK_ORDER_STATUS_PROCESSING = 3; // 处理中
    /**
     * 添加工单问题环节
     * @param $data
     * @return array|bool
     * @throws \Throwable
     */
    public function addTaskWorkOrderProblemStepCategory($data, $unionId)
    {
        $taskWorkOrder = model(TaskWorkOrderModel::class)->find($data['task_work_order_id']);
        if (empty($taskWorkOrder)) {
            throw new LogicException("task work order not exist", ErrorCode::TASK_WORK_ORDER_NOT_EXIST);
        }

        //自动获取配置内的人 $data
        $projectId = $taskWorkOrder['project_id'];

        $problemStepCategoryOptions = ProjectStepCategoryConfirmConfigService::getInstance()->selectUnionIdProjectStepCategoryOptions([
            'project_id' => $projectId,
            'step_category_id' => $data['step_category_id'],
            'type' => ProjectStepCategoryConfirmConfigModel::TYPE_TASK_WORK_ORDER
        ]);

        $data['project_id'] = $projectId;
        $taskWorkOrderProblemStepCategoryModel = model(TaskWorkOrderProblemStepCategoryModel::class);
        $result = $taskWorkOrderProblemStepCategoryModel->addItem($data);
        if (!$result) {
            throw_strack_exception($taskWorkOrderProblemStepCategoryModel->getError(), $taskWorkOrderProblemStepCategoryModel->getErrorCode());
        }
        //添加问题环节,拉人进入工单内
        $result['is_can_confirm'] = false;
        if (!empty($problemStepCategoryOptions)) {
            $userList = [];
            foreach ($problemStepCategoryOptions as $problemStepCategoryOptionsItem) {
                if (!$result['is_can_confirm'] && $unionId == $problemStepCategoryOptionsItem['confirm_union_id']) {
                    $result['is_can_confirm'] = true;
                }
                $userList[] = [
                    'id' => $problemStepCategoryOptionsItem['confirm_union_id']
                ];
            }
            TaskMemberService::getInstance()->addWorkOrderUser([
                'work_order_id' => $taskWorkOrder['id'],
                'user_list' => $userList
            ]);
        }

        return $result;
    }

    /**
     * 删除
     * @param $filter
     * @return array[]
     */
    public function delete($filter)
    {
        // 获取当前模块删除主键
        $taskWorkOrderProblemStepCategoryModel = model(TaskWorkOrderProblemStepCategoryModel::class);
        $taskWorkOrderProblemStepCategoryList = $taskWorkOrderProblemStepCategoryModel->field('id,task_work_order_id')->where($filter)->select();

        if (empty($taskWorkOrderProblemStepCategoryList)) {
            throw new LogicException('Delete item does not exist.', ErrorCode::DELETE_ITEM_NOT_EXIST);
        }

        $taskWorkOrderProblemStepCategoryIds = [];
        $taskWorkOrderIds = [];
        foreach ($taskWorkOrderProblemStepCategoryList as $taskWorkOrderProblemStepCategoryItem) {
            $taskWorkOrderProblemStepCategoryIds[] = $taskWorkOrderProblemStepCategoryItem['id'];
            $taskWorkOrderIds[] = $taskWorkOrderProblemStepCategoryItem['task_work_order_id'];
        }

        $resData = $taskWorkOrderProblemStepCategoryModel->deleteItem(['id' => ["IN", $taskWorkOrderProblemStepCategoryIds]]);


        if (!$resData) {
            // 通用删除失败错误码 003
            throw_strack_exception($taskWorkOrderProblemStepCategoryModel->getError(), ErrorCode::COMMON_DELETE_FAILURE);
        }

        //判定该工单是否还有问题环节
        $existProblemStepCategoryList = $taskWorkOrderProblemStepCategoryModel
            ->where(["task_work_order_id" => ["IN", $taskWorkOrderIds]])
            ->field("task_work_order_id,project_id")
            ->select();
        $newTaskWorkOrderIds = array_values(array_column($existProblemStepCategoryList, 'task_work_order_id', 'task_work_order_id'));
        //如果没有,则需要拉入所有qa
        $needPullMemberTaskWorkOrderIds = array_diff($taskWorkOrderIds, $newTaskWorkOrderIds);

        if (!empty($needPullMemberTaskWorkOrderIds)) {
            $projectIds = [];

            $projectTaskWorkOrderMap = [];

            //获取项目id
            $existProblemStepCategoryMap = model(TaskWorkOrderModel::class)->where([
                'id' => ['IN', $needPullMemberTaskWorkOrderIds]
            ])->field("id,project_id")->select();

            $existProblemStepCategoryMap = array_column($existProblemStepCategoryMap, 'project_id', 'id');
            foreach ($needPullMemberTaskWorkOrderIds as $needPullMemberTaskWorkOrderId) {
                $projectIds[] = $existProblemStepCategoryMap[$needPullMemberTaskWorkOrderId];
                $projectTaskWorkOrderMap[$existProblemStepCategoryMap[$needPullMemberTaskWorkOrderId]][] = $needPullMemberTaskWorkOrderId;
            }

            $projectMemberGroup = TaskWorkOrderService::getInstance()->getUnknownProblemStepCategoryMember($projectIds);
            foreach ($projectTaskWorkOrderMap as $projectId => $taskWorkOrderIdsItem) {
                if (empty($projectMemberGroup[$projectId])) {
                    continue;
                }

                $userList = [];
                foreach ($projectMemberGroup[$projectId] as $member) {
                    $userList[] = [
                        'id' => $member
                    ];
                }

                //给下面所有的工单拉入该项目的qa
                foreach ($taskWorkOrderIdsItem as $taskWorkOrderIdItem) {
                    $currentData = [
                        "user_list" => $userList,
                        "work_order_id" => $taskWorkOrderIdItem
                    ];

                    Client::send('add_task_work_order_user', build_queue_data_with_xu($currentData), 3);
                }
            }
        }


        return ['ids' => $taskWorkOrderProblemStepCategoryIds];
    }

    /**
     * 问题环节工单统计
     * @param $filter
     * @return array
     * @throws \think\Exception
     */
    public function problemStepCategoryTaskWorkOrderCount($filter,$tenant_id = 1)
    {

        $showStepCategoryGroup = ProjectService::getInstance()->getShowStepCategoryGroup();
        $allStepCategoryIds = [];
        foreach ($showStepCategoryGroup as $showStepCategoryGroupItem) {
            $childrenIds = $showStepCategoryGroupItem["children_ids"];
            $allStepCategoryIds = array_merge($allStepCategoryIds, $childrenIds);
        }
        if (empty($allStepCategoryIds)) {
            return [];
        }

        //默认时间为今天
        $startTime = $filter['start_time'] ?? strtotime(date('Y-m-d'));
        $endTime = $filter['end_time'] ?? strtotime(date('Y-m-d', strtotime('+1 day'))) - 1;
        $projectId = $filter['project_id'];
        //关联甲乙双方project_id
        $projectIds = $this->getProjectData($projectId, $tenant_id);

        $time = ["BETWEEN", [$startTime, $endTime]];
        $allStepCategoryIds = ["IN", $allStepCategoryIds];
        //发起工单 是 创建工单的环节
        //确认问题发起工单数
        $confirmSendTaskWorkOrderCount = $this->getProblemStepCategoryTaskWorkCount($projectIds, $time, $allStepCategoryIds, "confirm", "send");
        //未确认问题发起工单数
        $noConfirmSendTaskWorkOrderCount = $this->getProblemStepCategoryTaskWorkCount($projectIds, $time, $allStepCategoryIds, "no_confirm", "send");

        //收到工单是 工单里的选择问题的环节

        //确认接收工单数量
        $confirmReceiveTaskWorkOrderCount = $this->getProblemStepCategoryTaskWorkCount($projectIds, $time, $allStepCategoryIds, "confirm", "receive");

        //未确认接收工单数量
        $noConfirmReceiveTaskWorkOrderCount = $this->getProblemStepCategoryTaskWorkCount($projectIds, $time, $allStepCategoryIds, "no_confirm", "receive");

        foreach ($showStepCategoryGroup as $showStepCategoryGroupIndex => $showStepCategoryGroupItem) {
            $childrenIds = $showStepCategoryGroupItem["children_ids"];

            $confirmSendCount = 0;
            $noConfirmSendCount = 0;
            $confirmReceiveCount = 0;
            $noConfirmReceiveCount = 0;
            foreach ($childrenIds as $childrenId) {
                $confirmSendCount += $confirmSendTaskWorkOrderCount[$childrenId]['count'] ?? 0;
                $noConfirmSendCount += $noConfirmSendTaskWorkOrderCount[$childrenId]['count'] ?? 0;
                $confirmReceiveCount += $confirmReceiveTaskWorkOrderCount[$childrenId]['count'] ?? 0;
                $noConfirmReceiveCount += $noConfirmReceiveTaskWorkOrderCount[$childrenId]['count'] ?? 0;
            }
            $showStepCategoryGroupItem['confirm_send_count'] = $confirmSendCount;
            $showStepCategoryGroupItem['no_confirm_send_count'] = $noConfirmSendCount;
            $showStepCategoryGroupItem['confirm_receive_count'] = $confirmReceiveCount;
            $showStepCategoryGroupItem['no_confirm_receive_count'] = $noConfirmReceiveCount;
            $showStepCategoryGroup[$showStepCategoryGroupIndex] = $showStepCategoryGroupItem;
        }

        return $showStepCategoryGroup;
    }

    /**
     * @param $project_id
     * @param $tenant_id
     * @return mixed
     */
    private function getProjectData($project_id,$tenant_id)
    {
        $projectRes =  model(ProjectModel::class)->field(['id', 'name', 'belong_project_id', 'json', 'tenant_id','type'])
            ->where(['tenant_id' => $tenant_id,'belong_project_id' => $project_id])
            ->where(["json_unquote(json_extract(`json`,'$.project_status'))" => ['in',[self::PROJECT_STATUS_START, self::PROJECT_STATUS_COMPLETED, self::PROJECT_STATUS_IN_PROGRESS, self::PROJECT_STATUS_CANCEL]]])
            ->select();
        $projectIds = [];
        if (!empty($projectRes)) {
            $projectIds = array_unique(array_column($projectRes, 'id'));
        }
        array_push($projectIds, (string)$project_id);
        return $projectIds;
    }





    /**
     * 获取问题环节工单统计
     * @param $projectId
     * @param $time
     * @param $allStepCategoryIds
     * @param $isConfirm
     * @param $type
     * @return array
     */
    public function getProblemStepCategoryTaskWorkCount($projectId, $time, $allStepCategoryIds, $isConfirm, $type)
    {
        $filter = [
            'task_work_order.project_id' => ['IN',$projectId],
            'task_work_order.created' => $time
        ];

        $typeStepCategoryField = 'task_work_order_problem_step_category.step_category_id';

        $dbr = model(TaskWorkOrderModel::class);
        $filter[$typeStepCategoryField] = $allStepCategoryIds;
        $typeStepCategoryField = 'task_work_order.step_category_id';
        if ($type == 'send') {
            // 已确认
            if ($isConfirm == "confirm") {
                $filter['task_work_order_problem_step_category.is_confirm'] = ["IN", [TaskWorkOrderProblemStepCategoryModel::IS_CONFIRM_NO, TaskWorkOrderProblemStepCategoryModel::IS_CONFIRM_YES]];
                $dbr->join("task_work_order_problem_step_category on task_work_order_problem_step_category.task_work_order_id = task_work_order.id and task_work_order_problem_step_category.id in(select max(id) from task_work_order_problem_step_category as tt where tt.task_work_order_id = task_work_order.id and tt.is_confirm = 'yes' group by id) ");
            } else {
                // 未确认
                $filter['task_work_order_problem_step_category.is_confirm'] = TaskWorkOrderProblemStepCategoryModel::IS_CONFIRM_DEFAULT;
                $dbr->join("task_work_order_problem_step_category on task_work_order_problem_step_category.task_work_order_id = task_work_order.id and task_work_order_problem_step_category.id in(select max(id) from task_work_order_problem_step_category as tt where tt.task_work_order_id = task_work_order.id and tt.is_confirm not in ('yes') group by id) ");
            }
        }else{
            // 收到的工单
            if ($isConfirm == "confirm") {
                $filter['task_work_order_problem_step_category.is_confirm'] = ["IN", [TaskWorkOrderProblemStepCategoryModel::IS_CONFIRM_NO, TaskWorkOrderProblemStepCategoryModel::IS_CONFIRM_YES]];
                $dbr->join("task_work_order_problem_step_category on task_work_order_problem_step_category.task_work_order_id = task_work_order.id");
            } else {
                // 未确认
                $filter['task_work_order_problem_step_category.is_confirm'] = TaskWorkOrderProblemStepCategoryModel::IS_CONFIRM_DEFAULT;
                $dbr->join("task_work_order_problem_step_category on task_work_order_problem_step_category.task_work_order_id = task_work_order.id");
            }
        }
        // 工单统计排除掉已撤消的
        $filter['task_work_order.status'] = ['in' , [self::TASK_WORK_ORDER_STATUS_NOT_PROCESSED,self::TASK_WORK_ORDER_STATUS_PROCESSED,self::TASK_WORK_ORDER_STATUS_PROCESSING]];
        $list = $dbr->where($filter)->field($typeStepCategoryField . ",count(distinct task_work_order.id) as count")->group($typeStepCategoryField)->select();

        return array_column($list, null, 'step_category_id');
    }


    /**
     * 将检测工单问题环节是否所有为no
     * @param $id
     * @return void
     */
    public function checkTaskWorkOrderProblemStepCategoryIsAllNo($id)
    {
        if (is_array($id)) {
            $id = ["IN", $id];
        }

        $taskWorkOrderProblemStepCategory = model(TaskWorkOrderProblemStepCategoryModel::class)->where([
            'id' => $id
        ])->select();

        if (empty($taskWorkOrderProblemStepCategory)) {
            return;
        }

        //找到该工单的所有问题环节
        $taskWorkOrderIds = array_column($taskWorkOrderProblemStepCategory, 'task_work_order_id');
        $taskWorkOrderProblemStepCategoryMap = array_column($taskWorkOrderProblemStepCategory, null, 'id');
        $taskWorkOrderProblemStepCategoryList = model(TaskWorkOrderProblemStepCategoryModel::class)->where([
            'task_work_order_id' => ["IN", $taskWorkOrderIds]
        ])->select();

        //如果存在yes和default则不用拉入
        $isExistTaskWorkOrderIds = [];
        foreach ($taskWorkOrderProblemStepCategoryList as $taskWorkOrderProblemStepCategoryItem) {
            if (isset($taskWorkOrderProblemStepCategoryMap[$taskWorkOrderProblemStepCategoryItem['id']])) {
                $taskWorkOrderProblemStepCategoryItem['is_confirm'] = TaskWorkOrderProblemStepCategoryModel::IS_CONFIRM_NO;
            }
            if (in_array($taskWorkOrderProblemStepCategoryItem['is_confirm'], [TaskWorkOrderProblemStepCategoryModel::IS_CONFIRM_YES, TaskWorkOrderProblemStepCategoryModel::IS_CONFIRM_DEFAULT])) {
                $isExistTaskWorkOrderIds[$taskWorkOrderProblemStepCategoryItem['task_work_order_id']] = $taskWorkOrderProblemStepCategoryItem['project_id'];
            }
        }

        $problemStepCategoryTaskWorkOrderIdMap = array_column($taskWorkOrderProblemStepCategoryList, 'project_id', 'task_work_order_id');
        //比较出所有为no的工单id
        $needPullQaTaskWorkOrderIds = array_diff_key($problemStepCategoryTaskWorkOrderIdMap, $isExistTaskWorkOrderIds);
        if (!empty($needPullQaTaskWorkOrderIds)) {
            $projectId = array_values($needPullQaTaskWorkOrderIds);
            //拿取到项目下的qa
            $projectMemberGroup = TaskWorkOrderService::getInstance()->getUnknownProblemStepCategoryMember($projectId);
            foreach ($needPullQaTaskWorkOrderIds as $taskWorkOrderId => $projectId) {
                if (empty($projectMemberGroup[$projectId])) {
                    continue;
                }

                $userList = [];
                foreach ($projectMemberGroup[$projectId] as $member) {
                    $userList[] = [
                        'id' => $member
                    ];
                }

                //给下面所有的工单拉入该项目的qa
                $currentData = [
                    "user_list" => $userList,
                    "work_order_id" => $taskWorkOrderId
                ];

                Client::send('add_task_work_order_user', build_queue_data_with_xu($currentData));
            }
        }
    }

}
